#include "gcpch.h"
#include "gui_globals.h"
#include "gui_mainwnd.h"
#include "gui_listpane.h"
#include "media/resource.h"

// Main window presentation settings
#define GEEK_GUI_MAINWND_SPLITTER_WIDTH 3

static ATOM g_mainwnd_class_atom = 0;

static void clear_globals()
{
    g_mainwnd_class_atom = 0;
}

static void mainwnd_wm_size(geek_gui_mainwnd *wnd, int client_width, int client_height)
{
    if(client_width == 0 || client_height == 0)
    {
        return;
    }

    int available_width = client_width - GEEK_GUI_MAINWND_SPLITTER_WIDTH;
    int left_width = available_width / 2;
    int right_width = available_width - left_width;

    MoveWindow(wnd->panes[geek_gui_lpix_left].hwnd,0,0,left_width,client_height,TRUE);
    MoveWindow(wnd->panes[geek_gui_lpix_right].hwnd,left_width+GEEK_GUI_MAINWND_SPLITTER_WIDTH,0,right_width,client_height,TRUE);
}

static LRESULT CALLBACK mainwnd_wndproc(
    HWND hWnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam
    )
{
    geek_gui_mainwnd *mainwnd = reinterpret_cast<geek_gui_mainwnd *>(GetWindowLongPtr(hWnd,GWLP_USERDATA));
    
    if(mainwnd == NULL && uMsg != WM_NCCREATE)
    {
        return DefWindowProc(hWnd,uMsg,wParam,lParam);
    }

    switch(uMsg)
    {
    case WM_NCCREATE:
        SetWindowLongPtr(hWnd,GWLP_USERDATA,(LONG_PTR)((CREATESTRUCT *)lParam)->lpCreateParams);
        break;
    case WM_SIZE:
        mainwnd_wm_size(mainwnd,LOWORD(lParam),HIWORD(lParam));
        break;
    case WM_CLOSE:
        PostQuitMessage(0);
        break;
    }

    return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

static bool register_mainwnd_class()
{
    WNDCLASSEX wcex;
    memset(&wcex,0,sizeof(wcex));

    wcex.cbSize = sizeof(wcex);
    wcex.cbWndExtra = sizeof(geek_gui_mainwnd *);
    wcex.hCursor = LoadCursor(NULL,IDC_ARROW);
    wcex.hInstance = geek_gui_geekcmd_hinstance;
    wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
    wcex.hIcon = LoadIcon(geek_gui_geekcmd_hinstance,MAKEINTRESOURCE(IDI_GEEKCMD_APPLICATION));
    wcex.lpfnWndProc = &mainwnd_wndproc;
    wcex.lpszClassName = L"GEEKCMD_MAINWND";
    wcex.style = CS_HREDRAW|CS_VREDRAW;

    g_mainwnd_class_atom = RegisterClassEx(&wcex);
    return g_mainwnd_class_atom != 0;
}

bool geek_gui_mainwnd_init()
{
    clear_globals();
    return register_mainwnd_class();
}

void geek_gui_mainwnd_deinit()
{
    if(g_mainwnd_class_atom != 0)
    {
        UnregisterClass((LPCWSTR)g_mainwnd_class_atom,geek_gui_geekcmd_hinstance);
    }

    clear_globals();
}

static bool create_mainwnd_window(geek_gui_mainwnd *wnd)
{
    wchar_t namebuf[128];

    wsprintf(namebuf,L"Geek Commander %d.%d.%d",geek_version_major,geek_version_minor,geek_version_patch);
    wnd->hwnd = CreateWindowEx(
        0,
        (LPCWSTR)g_mainwnd_class_atom,
        namebuf,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        geek_gui_geekcmd_hinstance,
        wnd
        );

    return wnd->hwnd != NULL;
}

bool geek_gui_mainwnd_create(geek_gui_mainwnd *wnd, geek_gui_listpane *panes)
{
    memset(wnd,0,sizeof(geek_gui_mainwnd));
    wnd->panes = panes;
    
    if(!create_mainwnd_window(wnd))
    {
        goto error_exit;
    }

    for(int pane_ix = 0; pane_ix < geek_gui_lpix_count; ++pane_ix)
    {
        if(!geek_gui_listpane_create(&wnd->panes[pane_ix],wnd->hwnd))
        {
            goto error_exit;
        }
    }

    return true;

error_exit:
    geek_gui_mainwnd_destroy(wnd);
    return false;
}

void geek_gui_mainwnd_destroy(geek_gui_mainwnd *wnd)
{
    if(wnd->panes != NULL)
    {
        for(int pane_ix = 0; pane_ix < geek_gui_lpix_count; ++pane_ix)
        {
            geek_gui_listpane_destroy(&wnd->panes[pane_ix]);
        }
    }

    if(wnd->hwnd != NULL)
    {
        DestroyWindow(wnd->hwnd);
    }

    memset(wnd,0,sizeof(geek_gui_mainwnd));
}

bool geek_gui_mainwnd_msgloop_cycle()
{
    MSG msg;
    BOOL ret = GetMessage(&msg,NULL,0,0);

    if(ret == -1)
    {
        return false;
    }

    if(ret != 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    
    return ret != 0;
}
